#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
统一配置管理器
负责加载、合并和管理所有配置
"""

import os
import json
import yaml
from typing import Dict, Any, Optional, List
from .builtin_config_define import BuiltinConfigDefine
from .builtin_config import BuiltInConfig, ReservedSymbols, ObfuscationRules, FileFilters, AdvancedFeatures, LoggingConfig, ValidationConfig

class BuiltInConfigManager:
    """统一配置管理器"""

    def __init__(self, user_config_path: Optional[str] = None, logger=None):
        self.logger = logger
        self.builtin = BuiltinConfigDefine()
        self.user_config_data = self._load_user_config(user_config_path)
        self.final_config = self._create_config()
    
    def _load_user_config(self, path: Optional[str]) -> Dict[str, Any]:
        """
        加载用户配置文件
        path: 配置文件路径，支持JSON或YAML格式
        返回配置字典，如果文件不存在或无效则返回空字典
        """
        if not path:
            if self.logger:
                self.logger.log_operation("配置加载", "未提供用户配置文件，使用系统默认配置")
            return {}
        
        if not os.path.exists(path):
            if self.logger:
                self.logger.log_warning(f"用户配置文件不存在: {path}，使用系统默认配置")
            return {}
        
        try:
            with open(path, 'r', encoding='utf-8') as f:
                if path.endswith('.json'):
                    config_data = json.load(f)
                elif path.endswith(('.yml', '.yaml')):
                    config_data = yaml.safe_load(f)
                else:
                    raise ValueError(f"不支持的配置文件格式: {path}")
            
            if self.logger:
                self.logger.log_operation("配置加载", f"成功加载用户配置: {path}")
            return config_data or {}
            
        except json.JSONDecodeError as e:
            if self.logger:
                self.logger.log_error(f"JSON配置文件格式错误: {e}")
            raise ValueError(f"JSON配置文件格式错误: {e}")
        except yaml.YAMLError as e:
            if self.logger:
                self.logger.log_error(f"YAML配置文件格式错误: {e}")
            raise ValueError(f"YAML配置文件格式错误: {e}")
        except Exception as e:
            if self.logger:
                self.logger.log_error(f"加载用户配置失败: {e}")
            raise ValueError(f"加载用户配置失败: {e}")
    
    def _create_config(self) -> BuiltInConfig:
        """
        创建统一配置对象
        将用户配置与系统内置配置合并
        """
        # 创建基础配置
        config = BuiltInConfig()
        
        # 设置基础属性
        config.project_path = self.user_config_data.get('project_path', '')
        config.output_dir = self.user_config_data.get('output_dir', 'output')
        config.backup_dir = self.user_config_data.get('backup_dir', 'backups')
        config.temp_dir = self.user_config_data.get('temp_dir', 'temp') # 临时目录
        config.log_dir = self.user_config_data.get('log_dir', 'logs')
        config.dry_run = self.user_config_data.get('dry_run', False)
        config.mode = self.user_config_data.get('mode', 'mixed')
        config.platform = self.user_config_data.get('platform', 'auto')
        
        # 创建保留符号配置
        config.reserved_symbols = self._create_reserved_symbols()
        
        # 创建混淆规则配置
        config.obfuscation_rules = self._create_obfuscation_rules()
        
        # 创建文件过滤器配置
        config.file_filters = self._create_file_filters()
        
        # 创建高级功能配置
        config.advanced_features = self._create_advanced_features()
        
        # 创建日志配置
        config.logging = self._create_logging_config()
        
        # 创建验证配置
        config.validation = self._create_validation_config()
        
        # 设置符号过滤器
        config.symbol_min_length = self.user_config_data.get('symbol_filters', {}).get('min_length', 3)
        config.symbol_max_length = self.user_config_data.get('symbol_filters', {}).get('max_length', 50)
        config.exclude_symbol_prefixes = self.user_config_data.get('symbol_filters', {}).get('exclude_prefixes', ['_', 'test', 'Test'])
        config.exclude_symbol_suffixes = self.user_config_data.get('symbol_filters', {}).get('exclude_suffixes', ['Test', 'Spec', 'Mock'])
        
        return config
    
    def _create_reserved_symbols(self) -> ReservedSymbols:
        """
        创建保留符号配置
        将系统内置保留符号与用户自定义保留符号合并
        """
        reserved = ReservedSymbols()
        
        # 用户可以添加额外的保留词
        additional_reserved = self.user_config_data.get('additional_reserved', {})
        for language, symbols in additional_reserved.items():
            symbol_list = list(symbols) if isinstance(symbols, (list, tuple, set)) else [symbols]
            if language in reserved.language_keywords:
                existing = reserved.language_keywords[language]
                existing.extend(symbol_list)
                seen = set()
                reserved.language_keywords[language] = [
                    item for item in existing if not (item in seen or seen.add(item))
                ]
            else:
                reserved.language_keywords[language] = list(symbol_list)
        
        # 用户可以添加自定义模式
        reserved.user_patterns = list(self.user_config_data.get('additional_patterns', []))
        
        reserved.rebuild_indexes()
        return reserved
    
    def _create_obfuscation_rules(self) -> ObfuscationRules:
        """
        创建混淆规则配置
        """
        rules = ObfuscationRules()
        
        # 混淆规则
        obf_rules = self.user_config_data.get('obfuscation_rules', {})
        if obf_rules:
            rules.enabled_languages = obf_rules.get('enabled_languages', rules.enabled_languages)
            rules.symbol_types.update(obf_rules.get('symbol_types', {}))
            rules.naming_strategy = obf_rules.get('naming_strategy', rules.naming_strategy)
            rules.min_length = obf_rules.get('min_length', rules.min_length)
            rules.max_length = obf_rules.get('max_length', rules.max_length)
        
        # 随机化配置
        randomization = self.user_config_data.get('randomization', {})
        if randomization:
            rules.use_words_file = randomization.get('use_words_file', rules.use_words_file)
            rules.use_synonym_generator = randomization.get('use_synonym_generator', rules.use_synonym_generator)
            rules.random_prefix = randomization.get('prefix', rules.random_prefix)
            rules.random_suffix = randomization.get('suffix', rules.random_suffix)
            rules.fallback_chars = randomization.get('fallback_chars', rules.fallback_chars)
            rules.avoid_conflicts = randomization.get('avoid_conflicts', rules.avoid_conflicts)
        
        return rules
    
    def _create_file_filters(self) -> FileFilters:
        """
        创建文件过滤器配置
        """
        filters = FileFilters()
        
        file_filters = self.user_config_data.get('file_filters', {})
        if file_filters:
            filters.include_extensions = file_filters.get('include_extensions', filters.include_extensions)
            filters.exclude_directories = file_filters.get('exclude_directories', filters.exclude_directories)
            filters.exclude_files = file_filters.get('exclude_files', filters.exclude_files)
        
        return filters
    
    def _create_advanced_features(self) -> AdvancedFeatures:
        """
        创建高级功能配置
        """
        features = AdvancedFeatures()
        
        # 直接从高级功能配置中读取
        advanced = self.user_config_data.get('advanced_features', {})
        if advanced:
            # 死代码注入
            features.dead_code_enabled = advanced.get('dead_code_enabled', False)
            features.dead_code_complexity = advanced.get('dead_code_complexity', 'low')
            features.dead_code_branches_per_function = advanced.get('dead_code_branches_per_function', 2)
            features.dead_code_injection_probability = advanced.get('dead_code_injection_probability', 0.3)
            
            # 代码注入
            features.injection_enabled = advanced.get('injection_enabled', False)
            features.injection_content_file = advanced.get('injection_content_file', 'resources/inject.txt')
            features.injection_target_dirs = advanced.get('injection_target_dirs', [])
            features.injection_white_list_folders = advanced.get('injection_white_list_folders', [])
            
            # 垃圾代码生成
            features.dummy_code_enabled = advanced.get('dummy_code_enabled', False)
            features.dummy_code_count = advanced.get('dummy_code_count', 10)
            features.dummy_code_complexity = advanced.get('dummy_code_complexity', 'medium')
            features.dummy_code_white_list_folders = advanced.get('dummy_code_white_list_folders', [])
            features.dummy_code_add_properties = advanced.get('dummy_code_add_properties', True)
            features.dummy_code_linker_enabled = advanced.get('dummy_code_linker_enabled', True)
            features.dummy_code_linker_file = advanced.get('dummy_code_linker_file', 'DummyCodeLinker.m')
            
            # 深度混淆
            features.deep_obfuscation_enabled = advanced.get('deep_obfuscation_enabled', False)
            
            # 资源混淆
            features.resource_obfuscation_enabled = advanced.get('resource_obfuscation_enabled', False)
            features.image_obfuscation_enabled = advanced.get('image_obfuscation_enabled', False)
            features.rename_resources = advanced.get('rename_resources', False)
            features.modify_md5 = advanced.get('modify_md5', False)
            
            # Xcode集成
            features.xcode_auto_add = advanced.get('xcode_auto_add', False)
            features.xcode_project_file = advanced.get('xcode_project_file', '')
            features.xcode_target = advanced.get('xcode_target', '')
        
        return features
    
    def _create_logging_config(self) -> LoggingConfig:
        """
        创建日志配置
        """
        logging_config = LoggingConfig()
        
        # 基础日志配置
        logging_config.verbose = self.user_config_data.get('verbose', False)
        logging_config.log_file = self.user_config_data.get('log_file', logging_config.log_file)
        
        # 详细日志配置
        logging_data = self.user_config_data.get('logging', {})
        if logging_data:
            logging_config.log_level = logging_data.get('log_level', logging_config.log_level)
            logging_config.log_each_symbol = logging_data.get('log_each_symbol', logging_config.log_each_symbol)
            logging_config.colored_output = logging_data.get('colored_output', logging_config.colored_output)
        
        return logging_config
    
    def _create_validation_config(self) -> ValidationConfig:
        """
        创建验证配置
        """
        validation_config = ValidationConfig()
        
        # 基础验证配置
        validation_data = self.user_config_data.get('validation', {})
        if validation_data:
            validation_config.enabled = validation_data.get('enabled', validation_config.enabled)
            validation_config.levels = validation_data.get('levels', validation_config.levels)
            validation_config.fail_on_syntax_error = validation_data.get('fail_on_syntax_error', validation_config.fail_on_syntax_error)
            validation_config.fail_on_ast_error = validation_data.get('fail_on_ast_error', validation_config.fail_on_ast_error)
            validation_config.ide_validation_on_complete = validation_data.get('ide_validation_on_complete', validation_config.ide_validation_on_complete)
            validation_config.save_validation_reports = validation_data.get('save_validation_reports', validation_config.save_validation_reports)
            validation_config.max_errors_to_show = validation_data.get('max_errors_to_show', validation_config.max_errors_to_show)
        
        return validation_config
    
    def get_config(self) -> BuiltInConfig:
        """
        获取最终的统一配置
        """
        return self.final_config
    
    def validate_config(self) -> List[str]:
        """
        验证配置有效性
        """
        return self.final_config.validate()
    
    def save_config(self, output_path: str, format: str = 'json'):
        """
        保存当前配置到文件
        """
        config_dict = self._config_to_dict()
        
        try:
            with open(output_path, 'w', encoding='utf-8') as f:
                if format.lower() == 'json':
                    json.dump(config_dict, f, indent=2, ensure_ascii=False)
                elif format.lower() in ('yml', 'yaml'):
                    yaml.dump(config_dict, f, default_flow_style=False, allow_unicode=True)
                else:
                    raise ValueError(f"不支持的格式: {format}")
            
            if self.logger:
                self.logger.log_operation("配置保存", f"配置已保存到: {output_path}")
                
        except Exception as e:
            if self.logger:
                self.logger.log_error(f"保存配置失败: {e}")
            raise
    
    def _config_to_dict(self) -> Dict[str, Any]:
        """
        将配置对象转换为字典
        """
        config = self.final_config
        return {
            'project_path': config.project_path,
            'output_dir': config.output_dir,
            'backup_dir': config.backup_dir,
            'temp_dir': config.temp_dir,
            'dry_run': config.dry_run,
            'mode': config.mode,
            'platform': config.platform,
            'verbose': config.logging.verbose,
            'log_file': config.logging.log_file,
            
            'obfuscation_rules': {
                'enabled_languages': config.obfuscation_rules.enabled_languages,
                'symbol_types': config.obfuscation_rules.symbol_types,
                'naming_strategy': config.obfuscation_rules.naming_strategy,
                'min_length': config.obfuscation_rules.min_length,
                'max_length': config.obfuscation_rules.max_length
            },
            
            'file_filters': {
                'include_extensions': config.file_filters.include_extensions,
                'exclude_directories': config.file_filters.exclude_directories,
                'exclude_files': config.file_filters.exclude_files
            },
            
            'symbol_filters': {
                'min_length': config.symbol_min_length,
                'max_length': config.symbol_max_length,
                'exclude_prefixes': config.exclude_symbol_prefixes,
                'exclude_suffixes': config.exclude_symbol_suffixes
            },
            
            'randomization': {
                'use_words_file': config.obfuscation_rules.use_words_file,
                'use_synonym_generator': config.obfuscation_rules.use_synonym_generator,
                'prefix': config.obfuscation_rules.random_prefix,
                'suffix': config.obfuscation_rules.random_suffix,
                'fallback_chars': config.obfuscation_rules.fallback_chars,
                'avoid_conflicts': config.obfuscation_rules.avoid_conflicts
            },
            
            'advanced_features': {
                'injection': {
                    'enabled': config.advanced_features.injection_enabled,
                    'content_file': config.advanced_features.injection_content_file,
                    'target_dirs': config.advanced_features.injection_target_dirs
                },
                'dummy_code': {
                    'enabled': config.advanced_features.dummy_code_enabled,
                    'count': config.advanced_features.dummy_code_count,
                    'complexity': config.advanced_features.dummy_code_complexity
                },
                'resource_obfuscation': {
                    'enabled': config.advanced_features.resource_obfuscation_enabled,
                    'image_enabled': config.advanced_features.image_obfuscation_enabled,
                    'rename_resources': config.advanced_features.rename_resources,
                    'modify_md5': config.advanced_features.modify_md5
                }
            }
        }
